package cn.yunyichina.provider.pay.service.impl;

import cn.yunyichina.provider.framework.dubbo.service.AlipayService;
import cn.yunyichina.provider.framework.dubbo.service.WechatPayService;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.iface.entity.common.ResponseObject;
import cn.yunyichina.provider.pay.constant.AppType;
import cn.yunyichina.provider.pay.constant.MethodRouter;
import cn.yunyichina.provider.pay.constant.ResponseEnum;
import cn.yunyichina.provider.pay.exception.PaySettingNotFoundException;
import cn.yunyichina.provider.pay.service.BaseOpenidService;
import cn.yunyichina.provider.pay.service.OpenidService;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by Lullaby on 2016/10/18.
 */
@Service
public class OpenidServiceImpl extends BaseOpenidService implements OpenidService {

    private static final Logger logger = LoggerFactory.getLogger(OpenidServiceImpl.class);

    /**
     * 获取openid
     *
     * @param data
     * @return
     */
    public ResponseObject getOpenid(String data) {
        ResponseObject response = new ResponseObject();

        logger.info("OpenidServiceImpl.getOpenid.data -> {}", data);

        try {
            Map<String, String> dataMap = JSON.parseObject(data, Map.class);

            String appType = dataMap.get("app_type");
            switch (AppType.valueOf(appType)) {
                case WECHAT:
                    response = getWechatOpenid(dataMap);
                    break;
                case WXAPPLET:
                    response = getWxAppletOpenid(dataMap);
                    break;
                case ALIPAY:
                    response = getAlipayOpenid(dataMap);
                    break;
                default:
                    response.setResultCodeAndMessage(
                            ResponseEnum.UNKNOWN_APP_TYPE.getCode(),
                            ResponseEnum.UNKNOWN_APP_TYPE.getMessage()
                    );
                    break;
            }
        } catch (PaySettingNotFoundException e) {
            logger.error("PayServiceImpl.unifiedPay.PaySettingNotFoundException", e);
            response.setResultCodeAndMessage(
                    ResponseEnum.PAY_SETTING_NOT_FOUND.getCode(),
                    ResponseEnum.PAY_SETTING_NOT_FOUND.getMessage()
            );
        } catch (Exception e) {
            logger.error("OpenidServiceImpl.getOpenid.exception", e);
            response.setResultCodeAndMessage(
                    ResponseEnum.OPENID_EXCEPTION.getCode(),
                    ResponseEnum.OPENID_EXCEPTION.getMessage()
            );
        }

        return response;
    }

    /**
     * 获取微信openid
     *
     * @param params
     * @return
     */
    private ResponseObject getWechatOpenid(Map<String, String> params) throws PaySettingNotFoundException {
        ResponseObject response = new ResponseObject();

        if (checkOpenidParameters(params)) {
            Map<String, String> authParamsMap = buildWechatAuthParameters(params);
            String authParamsStr = JsonUtils.toJsonString(authParamsMap);

            logger.info("OpenidServiceImpl.getWechatOpenid.authParamsStr -> {}", authParamsStr);

            response = WechatPayService.callUnderlineFromInternalObject(
                    MethodRouter.WECHAT_ACCESS_TOKEN, authParamsStr
            );

            logger.info("OpenidServiceImpl.getWechatOpenid.response -> {}", JsonUtils.toJsonString(response));

            if (Response.SUCCESS_CODE.equals(response.getResultCode())) {
                Map<String, String> rpcResult = JsonUtils.parseObject(response.getResultObject(), Map.class);

                Map<String, String> result = new HashMap<>();
                result.put("access_token", rpcResult.get("access_token"));
                result.put("expires_in", rpcResult.get("expires_in"));
                result.put("refresh_token", rpcResult.get("refresh_token"));
                result.put("openid", rpcResult.get("openid"));
                result.put("scope", rpcResult.get("scope"));

                response.setResultObject(result);
            } else {
                response.setResultCodeAndMessage(
                        ResponseEnum.OPENID_WECHAT_EXCEPTION.getCode(),
                        ResponseEnum.OPENID_WECHAT_EXCEPTION.getMessage()
                );
            }
        } else {
            response.setResultCodeAndMessage(
                    ResponseEnum.Common.INVALID.getCode(),
                    ResponseEnum.Common.INVALID.getMessage()
            );
        }

        return response;
    }

    /**
     * 获取微信小程序openid
     *
     * @param params
     * @return
     */
    private ResponseObject getWxAppletOpenid(Map<String, String> params) throws PaySettingNotFoundException {
        ResponseObject response = new ResponseObject();

        if (checkOpenidParameters(params)) {
            Map<String, String> authParamsMap = buildWechatAppletOpenidParameters(params);
            String authParamsStr = JsonUtils.toJsonString(authParamsMap);

            logger.info("OpenidServiceImpl.getWxAppletOpenid.authParamsStr -> {}", authParamsStr);

            response = WechatPayService.callUnderlineFromInternalObject(
                    MethodRouter.WECHAT_WXAPPLET_OPENID, authParamsStr
            );

            logger.info("OpenidServiceImpl.getWxAppletOpenid.response -> {}", JsonUtils.toJsonString(response));

            if (response.isSuccess()) {
                Map<String, String> rpcResult = JsonUtils.parseObject(response.getResultObject(), Map.class);

                Map<String, String> result = new HashMap<>();
                result.put("openid", rpcResult.get("openid"));
                result.put("expires_in", rpcResult.get("expires_in"));

                response.setResultObject(result);
            } else {
                response.setResultCodeAndMessageAndResult(
                        ResponseEnum.OPENID_WXAPPLET_FAILURE.getCode(),
                        ResponseEnum.OPENID_WXAPPLET_FAILURE.getMessage(),
                        JsonUtils.parseObject(response.getResultObject(), Map.class)
                );
            }
        } else {
            response.setResultCodeAndMessage(
                    ResponseEnum.Common.INVALID.getCode(),
                    ResponseEnum.Common.INVALID.getMessage()
            );
        }

        return response;
    }

    /**
     * 获取支付宝openid
     *
     * @param params
     * @return
     */
    private ResponseObject getAlipayOpenid(Map<String, String> params) throws PaySettingNotFoundException {
        ResponseObject response = new ResponseObject();

        if (checkOpenidParameters(params)) {
            Map<String, String> authParamsMap = buildAlipayAuthParameters(params);
            String authParamsStr = JsonUtils.toJsonString(authParamsMap);

            logger.info("OpenidServiceImpl.getAlipayOpenid.authParamsStr -> {}", authParamsStr);

            response = AlipayService.callUnderlineFromInternalObject(
                    MethodRouter.ALIPAY_ACCESS_TOKEN, authParamsStr
            );

            logger.info("OpenidServiceImpl.getAlipayOpenid.response -> {}", JsonUtils.toJsonString(response));

            if (Response.SUCCESS_CODE.equals(response.getResultCode())) {
                Map<String, String> rpcResult = JsonUtils.parseObject(response.getResultObject(), Map.class);

                response.setResultObject(rpcResult);
            } else {
                response.setResultCodeAndMessage(
                        ResponseEnum.OPENID_ALIPAY_EXCEPTION.getCode(),
                        ResponseEnum.OPENID_ALIPAY_EXCEPTION.getMessage()
                );
            }
        } else {
            response.setResultCodeAndMessage(
                    ResponseEnum.Common.INVALID.getCode(),
                    ResponseEnum.Common.INVALID.getMessage()
            );
        }

        return response;
    }

}
